######################################################################
                                                                  
##      PROJECT TITLE:    How Campaigns Respond to Ballot Position                                        
##      PROJECT AUTHOR:   Saad Gulzar, Thomas Robinson, and Nelson Ruiz
##      EMAIL:            gulzar@stanford.edu         
                                                                  
##      DESCRIPTION:      Replication script for JOP paper                                          
                                                                  
######################################################################
#### 0. Package Dependencies ####
library(tidyverse)
library(haven)
library(lfe)
# Note: as of 16/12/20 lfe is down on CRAN
# Install via `remotes::install_version("lfe", version="2.8-5.1")`
library(xtable)
library(boot)
library(stargazer)
# devtools::install_github("ChandlerLutz/starpolishr")
library(starpolishr)

set.seed(89)

#### 1. Custom Functions ####

## Generate vector of summary statistics for variable (Tab A3)
sum_stat <- function(var, data) {
  vec <- c(sum(!is.na(data[[var]])),
           mean(data[[var]], na.rm = TRUE),
           sd(data[[var]], na.rm = TRUE),
           min(data[[var]], na.rm = TRUE),
           max(data[[var]], na.rm = TRUE))
  
  return(round(vec, 3))
}

## Add significance stars and convert into LaTeX row format (Tab A7)
pre_post_format <- function(mod) {
  coef <- mod$coefficients[1,1]
  se <- mod$coefficients[1,2]
  coef_sig <-  ifelse(coef/se > 2.576, "***",
                      ifelse(coef/se > 1.96, "**",
                             ifelse(coef/se > 1.64, "*","")))
  coef_print <- paste0(round(coef,3),coef_sig)
  se_print <- paste0("(",round(se,3),")")
  n <- mod$N
  
  res <- list(coef_print, se_print, "-","","-","",n)
}

## Format diff-in-diffs result for LaTeX table (Tab A7)
did_format <- function(mod) {
  mod_coef <- mod$coefficients[,1]
  mod_se <- mod$coefficients[,2]
  mod_sig <- ifelse(mod_coef/mod_se > 2.576, "***",
                    ifelse(mod_coef/mod_se > 1.96, "**",
                           ifelse(mod_coef/mod_se > 1.64, "*","")))
  mod_n <- mod$N
  
  mod_res <- list() #Blank for non-mod coef + SE
  for (i in 1:length(mod_coef)) {
    mod_res[[length(mod_res) + 1]] <- paste0(round(mod_coef[i],3),mod_sig[i])
    mod_res[[length(mod_res) + 1]] <- paste0("(",round(mod_se[i],3),")")
  }
  mod_res[[length(mod_res) + 1]] <- mod_n
  
  return(mod_res)
  
}

## Combine pre- and post-results (Tab A7)
make_table <- function(tab_list, path) {
  do.call("cbind",tab_list) %>%
    as.data.frame(.) %>%
    add_column(.before = 1,
               ` ` = c("Row = 1","",
                       "Post-Lottery","",
                       "Row = 1 x Post-Lottery","",
                       "N")) %>%
    
    xtable(.) %>%
    print(.,
          include.rownames = FALSE,
          include.colnames = FALSE,
          booktabs = TRUE,
          hline.after = NULL,
          only.contents = TRUE,
          file = path)
}

## Calculate average conditional direct effects
acde <- function(out, data) {
  
  f0 <- as.formula(paste0(out," ~ top_party | const_year + party_code | 0 | const_year"))
  f1 <- as.formula(paste0(out," ~ top_party + total_spending | const_year + party_code | 0 | const_year"))
  f2 <- as.formula(paste0("I(",out," - coef(first_stage)['total_spending']*total_spending) ~ top_party | const_year + party_code | 0 | const_year"))
  
  normal <-       felm(formula = f0, data)
  first_stage <-  felm(formula = f1, data)
  second_stage <- felm(formula = f2, data)
  
  sum0 <- summary(normal)
  sum1 <- summary(first_stage)
  sum2 <- summary(second_stage)
  
  
  full <- coef(normal) %>% as.numeric(.)
  acde <- coef(second_stage) %>% as.numeric(.)
  
  full_se <- sum0$coefficients[1,2] %>% as.numeric(.)
  acde_se <- sum2$coefficients[1,2] %>% as.numeric(.)
  
  output <- data.frame(dv = out, 
                       full = full, 
                       full_se = full_se,
                       acde = acde,
                       acde_se = acde_se)
  
  return(output)
  
}

#### 2. Data ####

## Campaign level data
camp <- c("total_101","total_102","total_103","total_104","total_105","total_106",
          "total_201","total_202","total_203","total_204","total_205","total_206",
          "total_207","total_208","total_209","total_210","total_211")

dvs <- c("total_income","total_spending",camp)

all_data <- read_csv("data/jop_councils_data.csv") %>% 
  mutate_at(camp, ~ (ifelse(is.na(.) & !is.na(total_income) & !is.na(total_spending),0,
                            ifelse(is.na(.),NA,.)))) %>% 
  mutate_at(dvs, ~ (./census))

vote_df <- all_data %>% 
  mutate(total_pub = total_public/census) %>% 
  filter(year == 2015,
         !is.na(total_income),
         !is.na(total_spending),
         !is.na(total_public))

race_df <- vote_df %>% 
  mutate(census_thous = census/1000,
         muni_party = paste0(muni_code,"_",party_code))

# Individual level dataset
ind_level <- read_csv("data/jop_individual_data.csv") %>% 
  mutate_at(c("total_spend_ind_pre","total_spend_pre","total_spend_ind_post",
              "total_spend_post","total_inc_ind","total_exp_ind",
              "total_106_ind"), 
            
            ~ (./census))

# Transaction-level data
trans_data <- read_csv("data/jop_transaction_data.csv")
  
######################################################################
#### 3. Main Text Tables ####
#### Table 1 ####
main_results <- data.frame(dv = as.character(),
                          coef = as.numeric(),
                          se = as.numeric(),
                          n = as.numeric(),
                          stringsAsFactors = FALSE)

outcomes <- c("vs_party","ss_party","total_party_seats",
              "total_income","total_spending","total_pub")

for (out in outcomes) {
  print(paste0("Running analysis on outcome variable: ",out))
  f_out <- as.formula(paste0(out," ~ top_party | const_year + party_code | 0 | const_year"))
  reg <- felm(data=vote_df, formula=f_out)
  
  main_results[nrow(main_results)+1,] <- list(out, 
                                            reg$coefficients[1], 
                                            summary(reg)$coefficients[1,2], 
                                            reg$N)
}

main_results$sig <- ifelse(main_results$coef/main_results$se > 2.576, "***",
                          ifelse(main_results$coef/main_results$se > 1.96, "**",
                                 ifelse(main_results$coef/main_results$se > 1.64, "*","")))

main_results$coef_print <- paste0(round(main_results$coef,3),main_results$sig)

elec_coefs <- main_results %>% .$coef_print

elec_ses <- main_results %>% mutate(se_print = paste0("(",round(se,3),")")) %>% .$se_print

elec_means <- vote_df %>% 
  filter(top_party == 0, 
         num_parties > 1) %>% 
  summarise(vs_mean = mean(vs_party),
            ss_mean = mean(ss_party),
            party_mean = mean(total_party_seats),
            rev_mean = mean(total_income),
            exp_mean = mean(total_spending),
            pub_mean = mean(total_pub)) %>% 
  as.numeric(.[1,])

elec_effect <- main_results %>% .$coef*100/elec_means

## Make Table 1
table_1 <- c()
table_1[1] <- paste0("Effect of Row = 1 & ",elec_coefs[1]," & ",elec_coefs[2]," & ",elec_coefs[3],
                     " & & ",elec_coefs[4]," & ",elec_coefs[5]," & ",elec_coefs[6],
                     " \\\\")

table_1[2] <- paste0(" & ",elec_ses[1]," & ",elec_ses[2]," & ",elec_ses[3],
                     " & & ",elec_ses[4]," & ",elec_ses[5]," & ",elec_ses[6],
                     " \\\\")

table_1[3] <- paste0("\\addlinespace Mean if Row $>$ 1",
                     " & ", round(elec_means[1],3),
                     " & ", round(elec_means[2],3),
                     " & ", round(elec_means[3],3),
                     " & & ",round(elec_means[4],3),
                     " & ", round(elec_means[5],3),
                     " & ", round(elec_means[6],3),
                     " \\\\")

table_1[4] <- paste0("Effect Size (\\%)",
                     " & ", round(elec_effect[1],3),
                     " & ", round(elec_effect[2],3),
                     " & ", round(elec_effect[3],3),
                     " & & ", round(elec_effect[4],3),
                     " & ", round(elec_effect[5],3),
                     " & ", round(elec_effect[6],3),
                     " \\\\")
n_ballots <- length(unique(vote_df$const_year))
table_1[5] <- paste0("\\midrule \\# Ballots",
                     " & ", n_ballots,
                     " & ", n_ballots,
                     " & ", n_ballots,
                     " & & ", n_ballots,
                     " & ", n_ballots,
                     " & ", n_ballots,
                     " \\\\")

table_1[6] <- paste0("\\# Observations",
                     " & ", main_results$n[1],
                     " & ", main_results$n[2],
                     " & ", main_results$n[3],
                     " & & ",main_results$n[4],
                     " & ",main_results$n[5],
                     " & ",main_results$n[6],
                     " \\\\")

write(print(table_1, quote = FALSE), file = "tables/tab1.tex")

######################################################################
#### 4. Appendix Tables ####
#### Table A1 ####
# Manually created text table

#### Table A2 ####
# Manually created text table

#### Table A3 ####
sum_df <- race_df

election_vars <- c("vs_party","ss_party","total_party_seats","census_thous","top_party")
election_names <- c("Vote Share","Seat Share","Party Seats","Registered Voters (Thousands)","Row = 1 on Ballot")

party_char <- c("party_size", "prev_vs_party", "prev_ss_party", "right", "traditional_party",
                "minority_party", "old")
party_names <- c("Num. of Municipalities Contested","2011 Vote Share(**)","2011 Seat Share(**)", 
                 "Right Party(***)","Traditional Party","Minority Party",
                 "Party Participated in the Last Election")

revenue <- c("total_income",  "total_101", "total_102", "total_103", "total_104", 
             "total_105", "total_106")
revenue_names <- c("Total","Candidate Income","Private Donations","Financial Credits",
                   "Events","State","Party Contributions")

expend <- c("total_spending", "total_pub", "total_201", "total_202", "total_203", 
            "total_204", "total_205", "total_206", "total_207", "total_208", "total_209",
            "total_210", "total_211")
exp_names <- c("Total","Advertising","Administrative","Office","Material","Public Acts",
               "Transport and Mail Service","Research","Judicial Cost","Electioneering",
               "Financial Fees","Exceed","Other")

# Build table
sum_stats <- data.frame("Variable" = as.character(),
                        "N" = as.numeric(),
                        "Mean" = as.numeric(),
                        "Sd" = as.numeric(),
                        "Min" = as.numeric(),
                        "Max" = as.numeric(),
                        stringsAsFactors = FALSE)

sum_stats[1,] <- c("\\textbf{\\textit{Panel A. Election Result}}","","","","","")

for (e  in 1:length(election_vars)) {
  sum_stats[nrow(sum_stats)+1,] <- c(election_names[e],sum_stat(election_vars[e], sum_df))
}

sum_stats[nrow(sum_stats)+1,] <- c("","","","","","")
sum_stats[nrow(sum_stats)+1,] <- c("\\textbf{\\textit{Panel B. Party Characteristics}}","","","","","")

for (p  in 1:length(party_char)) {
  sum_stats[nrow(sum_stats)+1,] <- c(party_names[p],sum_stat(party_char[p], sum_df))
}

sum_stats[nrow(sum_stats)+1,] <- c("","","","","","")
sum_stats[nrow(sum_stats)+1,] <- c("\\textbf{\\textit{Panel C. Campaign Financing}}","","","","","")
sum_stats[nrow(sum_stats)+1,] <- c("\\textbf{Revenues(*)}","","","","","")

for (r  in 1:length(revenue)) {
  sum_stats[nrow(sum_stats)+1,] <- c(revenue_names[r],sum_stat(revenue[r], sum_df))
}

sum_stats[nrow(sum_stats)+1,] <- c("\\textbf{Expenditures(*)}","","","","","")
for (ex  in 1:length(expend)) {
  sum_stats[nrow(sum_stats)+1,] <- c(exp_names[ex],sum_stat(expend[ex], sum_df))
}

xtable(sum_stats) %>% 
  print(., include.rownames = FALSE,
        floating = FALSE,
        sanitize.text.function = function (x){x},
        sanitize.colnames.function = function(x) {paste('{\\textbf{',x,'}}', sep ='')},
        file = "tables/tabA3.tex")

#### Table A4 ####
bal_df <- all_data

bal_df_comp <- bal_df %>% 
  filter(!is.na(total_income),
         !is.na(total_spending),
         !is.na(total_public))

balance_vars <- c("party_size","prev_vs_party","prev_ss_party","old","right",
                  "minority_party","traditional_party","camp_missing","open_list")

bal_regs <- list()
bal_N <- c()
for (bal_var in balance_vars) {
  
  bal_formula <- as.formula(paste0(bal_var," ~ top_party | const_year + party_code | 0  | const_year"))
  
  if (bal_var == "camp_missing") {
    bal_regs[[bal_var]] <- felm(bal_formula,data = bal_df)
  } else {
    bal_regs[[bal_var]] <- felm(bal_formula,data = bal_df_comp)
  }
  bal_N <- paste0(bal_N, " & ", bal_regs[[bal_var]]$N)
}

stargazer(bal_regs,
          covariate.labels = c("Effect of Row = 1"),
          star.cutoffs = c(0.1,0.05,0.01),
          table.layout  = "t",
          float = FALSE) %>% 
  
  star_insert_row(., paste0("\\midrule \\# Observations ",
                            bal_N,
                            " \\\\"),7) %>% 
  .[-c(1:4,9)] %>% 
  star_tex_write(., file = "tables/tabA4.tex")

#### Table A5 ####
agg_balance_vars <- c("women", "corrupt_before",
                  "sp", "lawsuits", "total_party_candidates", "retirado")

agg_data <- ind_level %>% 
  group_by(muni_party) %>% 
  summarise(top_party = unique(top_party), 
            women = mean(women, na.rm = TRUE),
            corrupt_before = mean(corrupt_before, na.rm = TRUE),
            sp = mean(sp, na.rm = TRUE),
            lawsuits = mean(lawsuits, na.rm = TRUE),
            const_year = unique(const_year),
            party_code = unique(party_code),
            total_party_candidates = unique(total_party_candidates),
            retirado = mean(retirado, na.rm = TRUE)) %>% 
  filter(muni_party %in% race_df$muni_party)

bal_regs_agg <- list()
bal_N_agg <- c()
for (bal_var in agg_balance_vars) {
  
  bal_formula_agg <- as.formula(paste0(bal_var," ~ top_party | const_year + party_code | 0 | const_year"))
  
  bal_regs_agg[[bal_var]] <- felm(bal_formula_agg, data = agg_data)
  
  bal_N_agg <- paste0(bal_N_agg, " & ", bal_regs_agg[[bal_var]]$N)
}

agg_tab <- stargazer(bal_regs_agg,
                     covariate.labels = c("Effect of Row = 1"),
                     star.cutoffs = c(0.1,0.05,0.01),
                     table.layout  = "t",
                     float = FALSE) %>% 
  
  star_insert_row(., paste0("\\midrule \\# Observations ",
                            bal_N_agg,
                            " \\\\"),7) %>% 
  .[-c(1:4,9)] %>% 
  star_tex_write(., file = "tables/tabA5.tex")

#### Table A6 ####

# Get control outcomes, means, and SDs
control_outcomes <- vote_df %>% 
  filter(top_party == 0) %>% 
  select(all_of(outcomes))

# Scale columns by control means
control_means <- colMeans(control_outcomes)
control_sds <- apply(control_outcomes, 2, sd)

vote_df_std <- vote_df
vote_df_std[,outcomes] <- scale(vote_df[,outcomes], center = control_means, scale = control_sds)

main_results_std <- data.frame(dv = as.character(),
                          coef = as.numeric(),
                          se = as.numeric(),
                          n = as.numeric(),
                          stringsAsFactors = FALSE)

for (out in outcomes) {
  print(paste0("Running analysis on outcome variable: ",out))
  f_out <- as.formula(paste0(out," ~ top_party | const_year + party_code | 0 | const_year"))
  reg <- felm(data=vote_df_std, formula=f_out)
  
  main_results_std[nrow(main_results_std)+1,] <- list(out, 
                                                    reg$coefficients[1], 
                                                    summary(reg)$coefficients[1,2], 
                                                    reg$N)
}

main_results_std$sig <- ifelse(main_results_std$coef/main_results_std$se > 2.576, "***",
                          ifelse(main_results_std$coef/main_results_std$se > 1.96, "**",
                                 ifelse(main_results_std$coef/main_results_std$se > 1.64, "*","")))

main_results_std$coef_print <- paste0(round(main_results_std$coef,3),main_results_std$sig)

elec_coefs <- main_results_std %>% .$coef_print

elec_ses <- main_results_std %>% mutate(se_print = paste0("(",round(se,3),")")) %>% .$se_print

table_1_std <- c()
table_1_std[1] <- paste0("Effect of Row = 1 & ",elec_coefs[1]," & ",elec_coefs[2]," & ",elec_coefs[3],
                     " & & ",elec_coefs[4]," & ",elec_coefs[5]," & ",elec_coefs[6],
                     " \\\\")

table_1_std[2] <- paste0(" & ",elec_ses[1]," & ",elec_ses[2]," & ",elec_ses[3],
                     " & & ",elec_ses[4]," & ",elec_ses[5]," & ",elec_ses[6],
                     " \\\\")

n_ballots <- length(unique(vote_df_std$const_year))
table_1_std[3] <- paste0("\\midrule \\# Ballots",
                     " & ", n_ballots,
                     " & ", n_ballots,
                     " & ", n_ballots,
                     " & & ", n_ballots,
                     " & ", n_ballots,
                     " & ", n_ballots,
                     " \\\\")

table_1_std[4] <- paste0("\\# Observations",
                     " & ", main_results_std$n[1],
                     " & ", main_results_std$n[2],
                     " & ", main_results_std$n[3],
                     " & & ",main_results_std$n[4],
                     " & ",main_results_std$n[5],
                     " & ",main_results_std$n[6],
                     " \\\\")

write(print(table_1_std, quote = FALSE), file = "tables/tabA6.tex")

#### Table A7 ####
outcomes_ind <- c("total_spend_ind_pre","total_spend_ind_post")

mp_spend <- ind_level %>%
  group_by(muni_party) %>%
  summarise_at(outcomes_ind, sum, na.rm = TRUE) %>%
  rename_all(~ str_replace(., "_ind",""))

mp_level <- vote_df %>%
  mutate(muni_party = paste0(muni_code,"_",party_code)) %>%
  left_join(mp_spend, by = "muni_party")

## Individual level analysis ##

mod_tab_ind <- list()
for (out in outcomes_ind) {
  bal_formula <- as.formula(paste0(out, " ~ top_party | const_year + party_code | 0  | muni_party"))
  mod_ind <- summary(felm(bal_formula, ind_level))
  
  res_ind <- pre_post_format(mod_ind)
  
  mod_tab_ind[[out]] <- res_ind
}

## Party-campaign level

outcomes_mp <- c("total_spend_pre","total_spend_post")

mod_tab_pc <- list()
for (out in outcomes_mp) {
  bal_formula <- as.formula(paste0(out, " ~ top_party | const_year + party_code | 0  | const_year"))
  mod_pc <- summary(felm(bal_formula, mp_level))
  
  res <- pre_post_format(mod_pc)
  
  mod_tab_pc[[out]] <- res
}

## Difference in Difference

# Party campaign level
did_spend <- mp_level %>%
  select(total_spend_pre, total_spend_post, top_party, const_year, party_code) %>%
  pivot_longer(cols = c(total_spend_pre, total_spend_post),
               names_to = "period", values_to = "spend") %>%
  mutate(period_bin = ifelse(str_detect(period,"_pre"),0,1)) %>%
  felm(spend ~ top_party * period_bin | const_year + party_code | 0  | const_year,
       data = ., keepX = TRUE) %>%
  summary(.)

mod_tab_pc[["Diff-in-Diff"]] <- did_format(did_spend)

# Ind. level
did_spend_ind <- ind_level %>%
  select(total_spend_ind_pre, total_spend_ind_post, top_party, const_year, party_code, muni_party) %>%
  pivot_longer(cols = c(total_spend_ind_pre, total_spend_ind_post),
               names_to = "period", values_to = "spend") %>%
  mutate(period_bin = ifelse(str_detect(period,"_pre"),0,1)) %>%
  felm(spend ~ top_party * period_bin | const_year + party_code | 0  | muni_party,
       data = ., keepX = TRUE) %>%
  summary(.)

mod_tab_ind[["Diff-in-Diff"]] <- did_format(did_spend_ind)

## Results table
# Panel A - Party-list
pc_results_tab <- make_table(mod_tab_pc,
                             path = "tables/tabA7a.tex")

# Panel B - Individual level
ind_results_tab <- make_table(mod_tab_ind,
                              path = "tables/tabA7b.tex")

#### Table A8 ####
## Manually generated text table

#### Table A9 ####
## Manually generated text table

#### Table A10 ####

revenue <- c("total_101", "total_102", "total_103", "total_104", 
             "total_105", "total_106")
revenue_names <- c("CandInc","PvtContr","Credits","Events","State","Party")

rev_mods <- list()
rev_means <- c()
rev_size <- c()
rev_clusters <- c()
for (r in  revenue) {
  f_rev <- as.formula(paste0(r,"~ top_party | const_year + party_code | 0 | const_year"))
  rev_mods[[r]] <- felm(f_rev, data = race_df)
  
  rev_means[r] <- mean(race_df[race_df$top_party  == 0, ][[r]])
  
  rev_size[r] <- round((rev_mods[[r]]$coefficients[1]/rev_means[r])*100,3)
  
  rev_clusters[r] <- length(unique(race_df[!is.na(race_df[[r]]),]$const_year))
}

rev_means_tex <- paste(" & ", round(rev_means, 3))
rev_size_tex <- paste(" & ", rev_size)
rev_clusters_tex <- paste(" & ", rev_clusters)
rev_N_tex <- paste(" & ",sapply(rev_mods, function (x) x[["N"]]))

stargazer(rev_mods,
          covariate.labels = "Effect of Row = 1",
          star.cutoffs = c(0.1,0.05,0.01),
          table.layout  = "t",
          float = FALSE) %>% 
  
  star_insert_row(., paste0(c("Mean if Row $>$ 1",rev_means_tex," \\\\"), collapse = ""),7) %>%
  star_insert_row(., paste0(c("Effect Size (\\%)",rev_size_tex," \\\\"), collapse = ""),8) %>% 
  
  star_insert_row(., paste0(c("\\midrule \\# Ballots",rev_clusters_tex," \\\\"), collapse = ""),9) %>% 
  star_insert_row(., paste0(c("\\# Observations",rev_N_tex," \\\\"), collapse = ""),10) %>% 
  
  .[-c(1:4,12)] %>% # removes tabular surround
  
  star_tex_write(., file = "tables/tabA10.tex")

#### Table A11 ####

expend <- c("total_201", "total_202", "total_203", "total_204", "total_205", "total_206", 
            "total_207", "total_208", "total_209","total_210", "total_211")
exp_names <- c("Admin","Office","Material","PubActs","TransMail","Research",
               "Judicial","Election","Fin","Exceed","Other")

exp_mods <- list()
exp_means <- c()
exp_size <- c()
exp_clusters <- c()
for (ex in expend) {
  f_ex <- as.formula(paste0(ex,"~ top_party | const_year + party_code | 0 | const_year"))
  exp_mods[[ex]] <- felm(f_ex, data = race_df)
  
  exp_means[ex] <- mean(race_df[race_df$top_party  == 0, ][[ex]])
  
  exp_size[ex] <- round((exp_mods[[ex]]$coefficients[1]/exp_means[ex])*100,3)
  
  exp_clusters[ex] <- length(unique(race_df[!is.na(race_df[[ex]]),]$const_year))
}

exp_means_tex <- paste(" & ", round(exp_means, 3))
exp_size_tex <- paste(" & ", exp_size)
exp_clusters_tex <- paste(" & ", exp_clusters)
exp_N_tex <- paste(" & ",sapply(exp_mods, function (x) x[["N"]]))

stargazer(exp_mods,
          covariate.labels = "Effect of Row = 1",
          star.cutoffs = c(0.1,0.05,0.01),
          table.layout  = "t",
          float = FALSE) %>% 
  
  star_insert_row(., paste0(c("Mean if Row $>$ 1",exp_means_tex," \\\\"), collapse = ""),7) %>%
  star_insert_row(., paste0(c("Effect Size (\\%)",exp_size_tex," \\\\"), collapse = ""),8) %>% 
  
  star_insert_row(., paste0(c("\\midrule \\# Ballots",exp_clusters_tex," \\\\"), collapse = ""),9) %>% 
  star_insert_row(., paste0(c("\\# Observations",exp_N_tex," \\\\"), collapse = ""),10) %>% 
  
  .[-c(1:4,12)] %>% # removes tabular surround
  
  star_tex_write(., file = "tables/tabA11.tex")

#### Table A12 ####
corr_df_robust <- race_df %>% 
  mutate(total_income = (total_income)/1000,
         total_spending = (total_spending)/1000) %>% 
  filter(top_party == 0)

corr_regs_robust <- list()
for (dep_var in c("vs_party","ss_party")) {
  for (ind_var in  c("total_income","total_spending")) {
    corr_df_robust$corr_treat <- corr_df_robust[[ind_var]]
    corr_formula <- as.formula(paste0(dep_var," ~ corr_treat | const_year + party_code | 0 | const_year"))
    corr_regs_robust[[paste0(ind_var,"_",dep_var)]] <- felm(corr_formula, data = corr_df_robust)
  }
}

stargazer(corr_regs_robust[["total_income_vs_party"]],
          corr_regs_robust[["total_income_ss_party"]],
          corr_regs_robust[["total_spending_vs_party"]],
          corr_regs_robust[["total_spending_ss_party"]],
          covariate.labels = "Effect of 1k Peso/Registered Voter",
          star.cutoffs = c(0.1,0.05,0.01),
          table.layout  = "t",
          float = FALSE) %>% 
  star_insert_row(., paste0("\\midrule \\# Ballots & ",
                            length(unique(corr_df_robust$const_year))," & ",
                            length(unique(corr_df_robust$const_year))," & ",
                            length(unique(corr_df_robust$const_year))," & ",
                            length(unique(corr_df_robust$const_year))," \\\\"),7) %>% 
  star_insert_row(., paste0("\\# Observations & ",
                            corr_regs_robust[["total_income_vs_party"]]$N," & ",
                            corr_regs_robust[["total_income_ss_party"]]$N," & ",
                            corr_regs_robust[["total_spending_vs_party"]]$N," & ",
                            corr_regs_robust[["total_spending_ss_party"]]$N," \\\\"),8) %>% 
  .[-c(1:4,10)] %>% 
  star_tex_write(., file = "tables/tabA12.tex")


#### Table A13 ####
corr_df <- race_df %>% 
  mutate(total_income = (total_income)/1000,
         total_spending = (total_spending)/1000)

corr_regs <- list()
for (dep_var in c("vs_party","ss_party")) {
  for (ind_var in  c("total_income","total_spending")) {
    corr_df$corr_treat <- corr_df[[ind_var]]
    corr_formula <- as.formula(paste0(dep_var," ~ corr_treat | const_year + party_code | 0 | const_year"))
    corr_regs[[paste0(ind_var,"_",dep_var)]] <- felm(corr_formula, data = corr_df)
  }
}

stargazer(corr_regs[["total_income_vs_party"]],corr_regs[["total_income_ss_party"]],
          corr_regs[["total_spending_vs_party"]],corr_regs[["total_spending_ss_party"]],
          covariate.labels = "Effect of 1k Peso/Registered Voter",
          star.cutoffs = c(0.1,0.05,0.01),
          table.layout  = "t",
          float = FALSE) %>% 
  star_insert_row(., paste0("\\midrule \\# Ballots & ",
                            length(unique(corr_df$const_year))," & ",
                            length(unique(corr_df$const_year))," & ",
                            length(unique(corr_df$const_year))," & ",
                            length(unique(corr_df$const_year))," \\\\"),7) %>% 
  star_insert_row(., paste0("\\# Observations & ",
                            corr_regs[["total_income_vs_party"]]$N," & ",
                            corr_regs[["total_income_ss_party"]]$N," & ",
                            corr_regs[["total_spending_vs_party"]]$N," & ",
                            corr_regs[["total_spending_ss_party"]]$N," \\\\"),8) %>% 
  .[-c(1:4,10)] %>% 
  star_tex_write(., file = "tables/tabA13.tex")

#### Table A14 ####

acde_outcomes <- c("vs_party","ss_party","total_party_seats")

acde_results <- do.call(
  "rbind", 
  lapply(acde_outcomes, function(x) acde(x, data = race_df))
  ) %>% 
  
  as.data.frame(.) %>% 
  mutate(indirect = ifelse(dv != "total_party_seats",(full - acde)*100,full-acde)) %>% 
  mutate(full_sig = ifelse(full/full_se > 2.576, "***",
                           ifelse(full/full_se > 1.96, "**",
                                  ifelse(full/full_se > 1.64, "*",""))),
         acde_sig = ifelse(acde/acde_se > 2.576, "***",
                           ifelse(acde/acde_se > 1.96, "**",
                                  ifelse(acde/acde_se > 1.64, "*",""))),
         full_print = paste0(round(full,3),full_sig),
         full_se_print = paste0("(",round(full_se,3),")"),
         acde_print = paste0(round(acde,3),acde_sig),
         acde_se_print = paste0("(",round(acde_se,3),")")) %>% 
  select(full_print,  full_se_print, acde_print, acde_se_print) %>% 
  t(.) %>% 
  as_tibble(.) %>% 
  add_column(.before = 1, var = c("ATE (Total Effect)","","ACDE (Direct Effect)","")) %>% 
  
  xtable(.) %>% 
  print(include.rownames = FALSE,
        include.colnames = FALSE,
        only.contents = TRUE,
        booktabs = TRUE,
        hline.after = 4,
        file = "tables/tabA14.tex")




######################################################################
#### 5. Appendix Figures ####
#### Figure A1 ####
## Example ballot

#### Figure A2 ####
row_results <- data.frame(election = as.character(),
                          row = as.numeric(),
                          dv = as.character(),
                          coef = as.numeric(),
                          se = as.numeric(),
                          n = as.numeric(),
                          stringsAsFactors = FALSE)


for (row in 1:max(race_df$party_row)) {
  tmp_df <- race_df %>% mutate(row_treat = ifelse(party_row == row,1,0))
  
  vs_reg <- felm(vs_party ~ row_treat | const_year + party_code | 0 | const_year, 
                 data = tmp_df, cmethod = "reghdfe") %>% summary(.)
  row_results[nrow(row_results)+1,] <- list("Councils", row, "vs_party", 
                                            vs_reg$coefficients[1,1], 
                                            vs_reg$coefficients[1,2], 
                                            vs_reg$N)
  
  ss_reg <- felm(ss_party ~ row_treat | const_year + party_code | 0 | const_year, 
                 data = tmp_df, cmethod = "reghdfe") %>% summary(.)
  row_results[nrow(row_results)+1,] <- list("Councils", row, "ss_party", 
                                            ss_reg$coefficients[1,1], 
                                            ss_reg$coefficients[1,2], 
                                            ss_reg$N)
  
  
  total_seats_reg <- felm(total_party_seats ~ row_treat | const_year + party_code | 0 | const_year, 
                          data = tmp_df, cmethod = "reghdfe") %>% summary(.)
  row_results[nrow(row_results)+1,] <- list("Councils", row, "total_party_seats", 
                                            total_seats_reg$coefficients[1,1], 
                                            total_seats_reg$coefficients[1,2], 
                                            total_seats_reg$N)
}

row_results %>% filter(row <= 10) %>% 
  mutate(dv = factor(ifelse(dv == "vs_party","Vote Share",
                            ifelse(dv == "ss_party","Seat Share","Seats")),
                     levels = c("Vote Share","Seat Share","Seats"))) %>% 
  ggplot(aes(x = row, y = coef, ymin = coef-1.96*se, ymax = coef+1.96*se)) +
  facet_grid(dv~., scales = "free") +
  geom_hline(yintercept = 0, linetype = "dashed") +
  geom_point() +
  geom_errorbar() +
  labs(x = "Row Position",
       y = "Effect of Row Position") +
  theme_bw() +
  theme(legend.position = "bottom") +
  ggsave("figures/fgA2.pdf", width = 15, height = 15, units = "cm")

#### Figure A3 ####

casc_row_results <- data.frame(election = as.character(),
                               row = as.numeric(),
                               dv = as.character(),
                               coef = as.numeric(),
                               se = as.numeric(),
                               n = as.numeric(),
                               stringsAsFactors = FALSE)

for (row in 1:10) {
  tmp_df <- race_df %>% mutate(row_treat = ifelse(party_row == row,1,
                                                  ifelse(party_row < row, NA,0))) %>% 
    filter(!is.na(row_treat))
  
  vs_reg <- felm(vs_party ~ row_treat | const_year + party_code | 0 | const_year, 
                 data = tmp_df, cmethod = "reghdfe") %>% summary(.)
  casc_row_results[nrow(casc_row_results)+1,] <- list("Councils", row, "vs_party", 
                                                      vs_reg$coefficients[1,1], 
                                                      vs_reg$coefficients[1,2], 
                                                      vs_reg$N)
  
  ss_reg <- felm(ss_party ~ row_treat | const_year + party_code | 0 | const_year, 
                 data = tmp_df, cmethod = "reghdfe") %>% summary(.)
  casc_row_results[nrow(casc_row_results)+1,] <- list("Councils", row, "ss_party", 
                                                      ss_reg$coefficients[1,1], 
                                                      ss_reg$coefficients[1,2], 
                                                      ss_reg$N)
  
  total_seats_reg <- felm(total_party_seats ~ row_treat | const_year + party_code | 0 | const_year, 
                          data = tmp_df, cmethod = "reghdfe") %>% summary(.)
  casc_row_results[nrow(casc_row_results)+1,] <- list("Councils", row, "total_party_seats", 
                                                      total_seats_reg$coefficients[1,1], 
                                                      total_seats_reg$coefficients[1,2], 
                                                      total_seats_reg$N)
}

casc_row_results %>% 
  filter(row <= 10) %>% 
  mutate(dv = ifelse(dv == "vs_party","Vote Share",
                     ifelse(dv == "ss_party","Seat Share","Seats"))) %>% 
  ggplot(aes(x = row, y = coef, ymin = coef-1.96*se, ymax = coef+1.96*se)) +
  facet_grid(dv~., scales = "free") +
  geom_hline(yintercept = 0, linetype = "dashed") +
  geom_point() +
  geom_errorbar() +
  labs(x = "Row Position",
       y = "Effect") +
  theme_bw() +
  theme(legend.position = "bottom") +
  ggsave("figures/fgA3.pdf", width = 15, height = 15, units = "cm")

#### Figure A4 ####
did_spend %>%
  .$coefficients %>%
  as_tibble(., rownames = "coef") %>%
  filter(str_detect(coef,"top")) %>%
  mutate(coef = ifelse(str_detect(coef, ":period"), "Post-lottery", "Pre-lottery"),
         coef = factor(coef, levels = c("Pre-lottery","Post-lottery"))) %>%
  rename(se = `Cluster s.e.`) %>%
  
  ggplot(aes(x = coef, y = Estimate)) +
  geom_point() +
  geom_errorbar(width = 0.3,
                aes(ymin = Estimate-1.96*se, ymax = Estimate+1.96*se)) +
  geom_hline(yintercept = 0, linetype = "dashed") +
  labs(y = "Effect of Row = 1", x = "") +
  theme_bw() +
  ggsave("figures/fgA4.pdf")

#### Figure A5 ####
pc_trans <- trans_data %>% 
  mutate(week2 = as.factor(weeks_from_lottery))

pc_trans_week <- pc_trans %>%
  group_by(muni_code, party_code, week2) %>%
  summarise(total_spend_week = sum(valor)) %>%
  left_join(mp_level, by = c("muni_code","party_code")) %>%
  mutate(total_spend_week_pc = total_spend_week/census)

mod_week <- felm(total_spend_week_pc ~ week2 + week2:top_party | const_year + party_code | 0  | const_year,
                 data = pc_trans_week, keepX = TRUE)

sum_week <- summary(mod_week)$coefficients %>%
  as_tibble(., rownames = "coef") %>%
  filter(str_detect(coef, ":")) %>%
  mutate(date = {gsub("week2","", coef) %>% gsub(":top_party","",.)},
         date = as.numeric(date)) %>%
  rename("se" = `Cluster s.e.`)

ggplot(sum_week, aes(x = date, y = Estimate)) +
  geom_point() +
  geom_errorbar(aes(ymin = Estimate - 1.96*se,
                    ymax = Estimate + 1.96*se)) +
  geom_hline(yintercept = 0, linetype = "solid") +
  geom_vline(xintercept = 0, linetype = "dashed") +
  annotate("text",x = 0.2, y = 60, label = "Ballot Order Lottery", angle = 90) +
  geom_vline(xintercept = 12, linetype = "dashed") +
  annotate("text", x = 12.2, y = 60, label = "Election", angle = 90) +
  labs(x = "Weeks since ballot order lottery", y = "Effect of Row = 1") +
  theme_bw()+
  ggsave("figures/fgA5.pdf", device = "pdf", width = 10, height = 5, dpi = 300)

#### Figure A6 & A7 ####

mean_outcomes <- c("total_exp_ind","total_inc_ind")
means_tabs <- list("total_exp_ind" = "fgA6","total_inc_ind" = "fgA7")
for (out in mean_outcomes) {
  ind_level %>% 
    select(out, open_list, rank, top_party) %>% 
    mutate(top_party = ifelse(top_party  == 1, "Top","Non-top"),
           open_list = ifelse(open_list == 1, "Open-list","Closed-list")) %>% 
    group_by(rank, top_party, open_list) %>% 
    summarise(av = mean(get(out), na.rm = TRUE),
              av_sd = sd(get(out), na.rm = TRUE),
              N = n()) %>% 
    filter(!is.na(top_party)) %>% 
    mutate(av_se = av_sd/sqrt(N)) %>% 
    
    ggplot(aes(x =  rank, y = av, color = top_party, shape = top_party)) +
    facet_wrap(~open_list, ncol = 2) +
    xlim(0,10.9) +
    geom_point() +
    geom_errorbar(aes(ymin = av-1.96*av_se, ymax = av+1.96*av_se)) +
    labs(y = "$ per voter (mean)", x = "Candidate Rank", color = "Party Position", shape = "Party Position") +
    theme_bw() +
    theme(legend.position = "bottom") +
    ggsave(paste0("figures/",means_tabs[[out]],".pdf"), width = 9, height = 6)
}

#### Figure A8 ####

rank_outcomes <- c("total_inc_ind","total_exp_ind")
ranks <- c("Top-ranked","Mid-ranked","Low-ranked")
pre_rank_results <- data.frame(dv = as.character(),
                               rank = as.character(),
                               list = as.character(),
                               coef = as.numeric(),
                               se = as.numeric(),
                               n = as.numeric(),
                               stringsAsFactors = FALSE)
for (out in rank_outcomes) {
  f_out <- as.formula(paste0(out," ~ top_party | const_year + party_code | 0 | muni_party"))
  out_name <- ifelse(out == "total_inc_ind","Total Revenue",
                     ifelse(out == "total_exp_ind", "Total Expenditure","Publicity Expenditure"))
  for (rank in ranks) {
    for (ltype in c("Open-list","Closed-list")) {
      ltype_bin <- ifelse(ltype == "Open-list",1,0)
      reg <- felm(data=ind_level[ind_level$position == rank & ind_level$open_list  == ltype_bin,], 
                  formula=f_out)
      pre_rank_results[nrow(pre_rank_results)+1,] <- list(out_name,
                                                          rank,
                                                          ltype,
                                                          reg$coefficients[1], 
                                                          summary(reg)$coefficients[1,2], 
                                                          reg$N)
    } 
    
  }
}

pre_rank_results$rank <- factor(pre_rank_results$rank, levels = ranks)
pre_rank_results$dv <- factor(pre_rank_results$dv, levels = c("Total Revenue", 
                                                              "Total Expenditure",
                                                              "Publicity Expenditure"))

pre_rank_results %>% 
  filter(list == "Open-list",
         dv != "Publicity Expenditure") %>% 
  ggplot(aes(x = rank, y = coef)) +
  facet_grid(dv~., scales = "free") +
  geom_point() +
  geom_errorbar(aes(ymin = coef-1.96*se, ymax = coef+1.96*se)) +
  geom_hline(yintercept = 0, linetype = "dashed") +
  labs(y = "Coefficient", x = "Candidate Rank") +
  theme_bw() +
  ggsave("figures/fgA8.pdf", width = 5, height = 7)

#### Figure A9 ####

pre_rank_results %>% 
  filter(list == "Closed-list",
         dv != "Publicity Expenditure") %>% 
  ggplot(aes(x = rank, y = coef)) +
  facet_grid(dv~., scales = "free") +
  geom_point() +
  geom_errorbar(aes(ymin = coef-1.96*se, ymax = coef+1.96*se)) +
  geom_hline(yintercept = 0, linetype = "dashed") +
  labs(y = "Coefficient", x = "Candidate Rank") +
  theme_bw() +
  ggsave("figures/fgA9.pdf", width = 5, height = 7)

#### Figure A10 ####

pc_fin_results <- data.frame(dv = as.character(),
                               rank = as.character(),
                               list = as.character(),
                               coef = as.numeric(),
                               se = as.numeric(),
                               n = as.numeric(),
                               stringsAsFactors = FALSE)

f_out <- as.formula("total_106_ind ~ top_party | const_year + party_code | 0 | muni_party")
out_name <- "Party Spending"
for (rank in ranks) {
  for (ltype in c("Open-list","Closed-list")) {
    ltype_bin <- ifelse(ltype == "Open-list",1,0)
    reg <- felm(data=ind_level[ind_level$position == rank & ind_level$open_list  == ltype_bin,], 
                formula=f_out)
    pc_fin_results[nrow(pc_fin_results)+1,] <- list(out_name,
                                                    rank,
                                                    ltype,
                                                    reg$coefficients[1], 
                                                    summary(reg)$coefficients[1,2], 
                                                    reg$N)
  } 
  
}

pc_fin_results$rank <- factor(pc_fin_results$rank, levels = ranks)

pc_fin_results %>% 
  mutate(rank = factor(rank, levels = ranks)) %>% 
  ggplot(aes(x = rank, y = coef)) +
  facet_grid(.~list, scales = "free") +
  geom_point() +
  geom_errorbar(aes(ymin = coef-1.96*se, ymax = coef+1.96*se)) +
  geom_hline(yintercept = 0, linetype = "dashed") +
  labs(y = "Effect of Row = 1", x = "Candidate Rank") +
  theme_bw() +
  ggsave("figures/fgA10.pdf", width = 5, height = 7)

